import type {Recordable} from "../types";
import {isArray, isDate, isNullOrUnDef, isObject, isRegExp} from "./assert";

/**
 * 深度合并对象
 * @param src
 * @param target
 */
export const deepMerge = <T = Recordable>(src: Recordable = {}, target: Recordable = {}): T => {
    let key: string;
    for (key of Object.keys(target)) {
        src[key] = isObject(src[key])
            ? deepMerge(src[key], target[key])
            : target[key];
    }
    return src as T;
};

/**
 * 排除对象key
 * @param obj
 * @param fields
 */
export const omit = <T extends object, K extends keyof T>(obj: T, fields: K[]): Omit<T, K> => {
    const shallowCopy = Object.assign({}, obj);
    for (let field of fields) {
        delete shallowCopy[field]
    }
    return shallowCopy
}

/**
 * 克隆对象
 * @param target
 */
export const deepClone = <T>(target: T): T => {
    if (isNullOrUnDef(target)) return target;
    if (isDate(target)) return new Date(target) as T;
    if (isRegExp(target)) return new RegExp(target) as T;
    let clone: any = target;
    if (isArray(target)) {
        clone = [];
        for (let i = 0; i < target.length; i++) {
            clone.push(deepClone(target[i]));
        }
    } else if (isObject(target)) {
        clone = {};
        for (let key in target) {
            if (target.hasOwnProperty(key)) {
                clone[key] = deepClone(target[key]);
            }
        }
    }
    return clone;
}

/**
 * 过滤掉undefined的key
 * @param obj
 */
export const filterUndefinedKeys = <T = Recordable>(obj: T): T => {
    for (let key in obj) {
        if (obj[key] === undefined) {
            delete obj[key];
        }
    }
    return obj;
}

/**
 * 解析JSON串
 * @param str
 * @param initValue
 */
export const jsonParse = <T extends Record<string, unknown>>(
    str: string,
    initValue?: T,
): T | unknown => {
    try {
        return JSON.parse(str);
    } catch {
        return initValue ?? {};
    }
};